﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using XLua;
using System.Text;

namespace ZL_Framework
{
    /// <summary>
    /// Lua管理器
    /// </summary>
    public class LuaManager : MonoSingleton<LuaManager>
    {
        private LuaEnv m_luaenv;
        private LuaTable scriptEnv;
        private Action ondestroy = null;
        public LuaSerializeFile LuaFile;

        public LuaEnv Luaenv
        {
            get
            {
                return m_luaenv;
            }
        }

        protected override void Destroy()
        {
            //mainInjections = null;
            ondestroy?.Invoke();
            scriptEnv?.Dispose();
        }

        public void StartLua()
        {
            LuaFile = AssetBundlesManager.Instance.LuaFile;
            m_luaenv = new LuaEnv();
            m_luaenv.AddLoader(Loader);
            scriptEnv = m_luaenv.NewTable();
            LuaTable meta = m_luaenv.NewTable();
            meta.Set("__index", m_luaenv.Global);
            scriptEnv.SetMetaTable(meta);
            meta.Dispose();

            m_luaenv.DoString(LoadLua("main"), "main", scriptEnv);

            //foreach (var injection in mainInjections)
            //{
            //    scriptEnv.Set(injection.name, injection.value);
            //}
            scriptEnv.Set("self", this);


            ondestroy = scriptEnv.Get<Action>("ondestroy");
            scriptEnv.Get<Action>("awake")?.Invoke();
        }

        private string LoadLua(string filePath)
        {
            if (AppConfig.IsSimulate && Application.isEditor)
            {
                string fullPath = AppConfig.LuaFilePath + filePath + ".lua";

                LogTool.Instance.Log("Lua Path: " + fullPath);
                return File.ReadAllText(fullPath);
            }
            else
            {
                return GetLuaFileString(filePath);
            }
        }

        private byte[] Loader(ref string filepath)
        {
            if (AppConfig.IsSimulate && Application.isEditor)
            {
                string fullPath;
                RecursionLuaFilePath(AppConfig.LuaFilePath, filepath + ".lua", out fullPath);
                //Debug.Log("Load : " + fullPath);
                return Encoding.UTF8.GetBytes(File.ReadAllText(fullPath));
            }
            else
            {
                return GetLuaFileBytes(filepath);
            }
        }

        private void RecursionLuaFilePath(string dirPath, string fileName, out string fileFullPath)
        {
            fileFullPath = null;
            string[] filesPath = Directory.GetFiles(dirPath);
            for (int i = 0; i < filesPath.Length; i++)
            {
                FileInfo fileInfo = new FileInfo(filesPath[i]);
                if (fileInfo.Name.Equals(fileName))
                {

                    fileFullPath = fileInfo.FullName;
                    return;
                }
            }
            string[] childrenPath = Directory.GetDirectories(dirPath);
            for (int i = 0; i < childrenPath.Length; i++)
            {
                // 这里避免取到值以后的重复递归  也可以使用抛出异常的方式直接退出
                if (!string.IsNullOrEmpty(fileFullPath))
                    return;
                RecursionLuaFilePath(childrenPath[i], fileName, out fileFullPath);
            }
        }


        public string GetLuaFileString(string fileName)
        {
            if (LuaFile != null && LuaFile.files != null && LuaFile.fileMap.ContainsKey(fileName))
            {
                return Encoding.UTF8.GetString(LuaFile.fileMap[fileName]);
            }
            else
            {
                return string.Empty;
            }
        }

        public byte[] GetLuaFileBytes(string fileName)
        {
            if (LuaFile != null && LuaFile.fileMap != null && LuaFile.fileMap.ContainsKey(fileName))
            {
                return LuaFile.fileMap[fileName];
            }
            else
            {
                return new byte[] { };
            }
        }

        public void Update()
        {
            if (m_luaenv != null)
            {
                m_luaenv.Tick();
            }
        }
    }


    [System.Serializable]
    public class Injection
    {
        public string name;
        public GameObject value;
    }
}